package com.liangyu.util;

import org.springframework.lang.Nullable;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.springframework.util.StringUtils.delimitedListToStringArray;
import static org.springframework.util.StringUtils.hasText;

/**
 * 字符串工具类
 *
 * @author hy
 */
public class StringUtil {


    /**
     * 字符串是否为空
     *
     * @param str
     * @return
     */
    public static boolean isNullOrEmpty(Object str) {
        if (str == null) {
            return true;
        }
        str = str.toString().trim();
        return str.equals("");
    }
    public static String valueOf(Object obj) {
        return (obj == null) ? "" : obj.toString();
    }
    /**
     * 忽略大小写比较
     *
     * @param src
     * @param dest
     * @return
     */
    public static boolean equalsIgnoreNullCase(String src, String dest) {
        if (!StringUtil.isNullOrEmpty(src)) {
            return src.equalsIgnoreCase(dest);
        } else {
            return false;
        }
    }

    /**
     * 删除开头字符串
     *
     * @param str
     * @param startStr
     * @return
     */
    public static String deleteStartStr(String str, String startStr) {
        if (str.startsWith(startStr)) {
            return str.substring(str.indexOf(startStr));
        } else {
            return str;
        }
    }

    /**
     * 删除结尾字符串
     *
     * @param str    原字符串
     * @param endStr 结尾的字符串
     * @return 返回新的字符串
     */
    public static String deleteEndStr(String str, String endStr) {
        if (str.endsWith(endStr)) {
            return str.substring(0, str.lastIndexOf(endStr));
        } else {
            return str;
        }
    }

    /**
     * 设置首字母小写
     *
     * @param str 原字符串
     * @return 设置后的字符串
     */
    public static String setFirstLower(String str) {
        if (!isNullOrEmpty(str)) {
            char firstChar = str.charAt(0);
            if (Character.isUpperCase(firstChar)) {
                char[] strChars = str.toCharArray();
                strChars[0] = Character.toLowerCase(firstChar);

                return new String(strChars);
            }
        }
        return str;
    }

    /**
     * 设置首字母大写
     *
     * @param str 字符串
     * @return
     */
    public static String setFirstUpper(String str) {
        if (!isNullOrEmpty(str)) {
            char firstChar = str.charAt(0);
            if (Character.isLowerCase(firstChar)) {
                char[] strChars = str.toCharArray();
                strChars[0] = Character.toUpperCase(firstChar);

                return new String(strChars);
            }
        }
        return str;
    }

    /**
     * 如果字符串尾部不存在指定字符串则附加
     *
     * @param str       原字符串
     * @param appendStr 要附加的字符串
     * @return 附加后的字符串
     */
    public static String appendWhenNotExist(String str, String appendStr) {
        if (!str.endsWith(appendStr)) {
            str += appendStr;
        }
        return str;
    }

    /**
     * 替换字符串
     *
     * @param str    字符串
     * @param oldStr 旧的字符串
     * @param newStr 新的字符串
     * @return
     */
    public static String replace(String str, String oldStr, String newStr) {
        if (oldStr == null)
            oldStr = "";
        if (newStr == null)
            newStr = "";

        if (!isNullOrEmpty(str)) {
            return str.replace(oldStr, newStr);
        } else {
            return str;
        }
    }

    private static String[] str = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    /**
     * 获取随机字符串
     *
     * @return
     */
    public static String getRandomString(int length) {
        if (length <= 0) {
            throw new IllegalArgumentException("随机字符串的长度必须大于0");
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int value = (int) (Math.random() * 48);
            sb.append(str[value]);
        }
        return sb.toString();
    }

    /**
     * 获取随机参数名
     *
     * @param prefix 参数前缀
     * @param length 参数长度
     * @return
     */
    public static String getRandomString(String prefix, int length) {
        String randomStr = getRandomString(length);
        if (!isNullOrEmpty(prefix)) {
            return prefix + randomStr;
        } else {
            return randomStr;
        }
    }

    /**
     * 格式化字符串，忽略NULL值，将NULL值转为空
     *
     * @param format
     * @param args
     * @return
     */
    public static String formatStringIgnoreNull(String format, String... args) {
        String[] params = args;
        if (params != null && params.length > 0) {
            Object[] formatArgs = new Object[params.length];
            for (int i = 0; i < params.length; i++) {
                if (params[i] == null) {
                    formatArgs[i] = "";
                } else {
                    formatArgs[i] = params[i];
                }
            }
            return String.format(format, formatArgs);
        } else {
            return format;
        }
    }

    /**
     * 转变字符串列表为字符串
     *
     * @param strs
     * @return
     */
    public static String convertListToString(List<String> strs) {
        return convertListToString(strs, ",");
    }

    /**
     * 转变字符串列表为字符串
     *
     * @param strs       字符串列表
     * @param insertText 中间插入的字符
     * @return
     */
    public static String convertListToString(List<String> strs, String insertText) {
        if (strs == null) {
            throw new IllegalArgumentException("传入的字符串列表必须不为空。");
        }

        StringBuilder sb = new StringBuilder();
        int i = 0;
        boolean needInsert = !StringUtil.isNullOrEmpty(insertText);
        for (String str : strs) {
            if (i > 0 && needInsert) {
                sb.append(insertText);
            }
            sb.append(str);
            i++;
        }

        return sb.toString();
    }

    /**
     * 分割字符串 ，默认使用逗号分隔
     *
     * @param str
     * @return
     */
    public static List<String> splitString(String str) {
        return splitString(str, ",");
    }

    /**
     * 分割字符串
     *
     * @param str
     * @param splitStr
     * @return
     */
    public static List<String> splitString(String str, String splitStr) {
        if (StringUtil.isNullOrEmpty(str)) {
            throw new IllegalArgumentException("输入的字符串参数不允许为空。");
        }
        if (StringUtil.isNullOrEmpty(splitStr)) {
            throw new IllegalArgumentException("分割字符串参数不允许为空。");
        }

        String[] splits = str.split(splitStr);
        List<String> result = new ArrayList<String>();
        if (splits != null) {
            for (int i = 0; i < splits.length; i++) {
                result.add(splits[i].trim());
            }
        }
        return result;
    }

    /**
     * 分割字符串
     *
     * @param str
     * @param splitStr
     * @return
     */
    public static List<String> splitStringNoThrows(String str, String splitStr) {
        if (StringUtil.isNullOrEmpty(str)) {
            // throw new IllegalArgumentException("输入的字符串参数不允许为空。");
            return new ArrayList<>();
        }
        if (StringUtil.isNullOrEmpty(splitStr)) {
            // throw new IllegalArgumentException("分割字符串参数不允许为空。");
            return new ArrayList<>();
        }

        String[] splits = str.split(splitStr);
        List<String> result = new ArrayList<String>();
        if (splits != null) {
            for (int i = 0; i < splits.length; i++) {
                result.add(splits[i].trim());
            }
        }
        return result;
    }

    /**
     * 重叠字符串
     *
     * @param str
     * @param times
     * @return
     */
    public static String duplicateString(String str, int times) {
        return duplicateString(str, times, ",");
    }

    /**
     * 重叠字符串
     *
     * @param str
     * @param times
     * @param insertStr
     * @return
     */
    public static String duplicateString(String str, int times, String insertStr) {
        if (StringUtil.isNullOrEmpty(str)) {
            throw new IllegalArgumentException("输入的字符串参数不允许为空。");
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < times; i++) {
            if (i > 0) {
                sb.append(insertStr);
            }
            sb.append(str);
        }
        return sb.toString();
    }

    /**
     * escape字符串对应js中的escape
     *
     * @param src
     * @return
     */
    public static String escape(String src) {
        int i;
        char j;
        StringBuffer tmp = new StringBuffer();
        tmp.ensureCapacity(src.length() * 6);

        for (i = 0; i < src.length(); i++) {

            j = src.charAt(i);

            if (Character.isDigit(j) || Character.isLowerCase(j) || Character.isUpperCase(j))
                tmp.append(j);
            else if (j < 256) {
                tmp.append("%");
                if (j < 16)
                    tmp.append("0");
                tmp.append(Integer.toString(j, 16));
            } else {
                tmp.append("%u");
                tmp.append(Integer.toString(j, 16));
            }
        }
        return tmp.toString();
    }

    /**
     * unescape字符串对应js中的unescape
     *
     * @param src
     * @return
     */
    public static String unescape(String src) {
        StringBuffer tmp = new StringBuffer();
        tmp.ensureCapacity(src.length());
        int lastPos = 0, pos = 0;
        char ch;
        while (lastPos < src.length()) {
            pos = src.indexOf("%", lastPos);
            if (pos == lastPos) {
                if (src.charAt(pos + 1) == 'u') {
                    ch = (char) Integer.parseInt(src.substring(pos + 2, pos + 6), 16);
                    tmp.append(ch);
                    lastPos = pos + 6;
                } else {
                    ch = (char) Integer.parseInt(src.substring(pos + 1, pos + 3), 16);
                    tmp.append(ch);
                    lastPos = pos + 3;
                }
            } else {
                if (pos == -1) {
                    tmp.append(src.substring(lastPos));
                    lastPos = src.length();
                } else {
                    tmp.append(src.substring(lastPos, pos));
                    lastPos = pos;
                }
            }
        }
        return tmp.toString();
    }

    public static boolean isBlank(final CharSequence cs) {
        return !hasText(cs);
    }

    /**
     * 如果字符窜为null或者为空或者=='null' 用指定字符窜替代
     *
     * @param str
     * @param replaceStr
     * @return
     */
    public static String isNullReplace(String str, String replaceStr) {
        if (StringUtil.isNullOrEmpty(replaceStr)) {
            replaceStr = "";
        }
        if (StringUtil.isNullOrEmpty(str) || "null".equals(str)) {
            return replaceStr;
        }
        return str.trim();
    }

    /**
     * 字符串右补齐空格
     *
     * @param n 字符总长度
     * @param s 字符传
     * @return
     */
    public static String rightFill(int n, String s) {
        if (s.length() >= n)
            return s;
        return String.format("%-" + n + "s", s);
    }

    /**
     * base64编码
     *
     * @param encodeBytes:要编码的字符串
     * @return
     */
    public static String base64Encode(byte[] encodeBytes) {
        return Base64.getEncoder().encodeToString(encodeBytes);
    }

    /**
     * base64解码
     *
     * @param decodeStr:要解码的字符串
     * @return
     */
    public static byte[] base64Decode(String decodeStr) {
        return Base64.getDecoder().decode(decodeStr);
    }

    /**
     * 字符串移位
     *
     * @param s:要移位的字符串
     * @param digits:向左移动的位数
     */
    public static String shift(String s, int digits) {
        if (digits == 0) {
            return s;
        } else if (digits > 0) {
            int lDigits = digits % s.length();
            String left = reverStr(s.substring(0, lDigits));
            String right = reverStr(s.substring(lDigits));
            return reverStr(left + right);
        } else { // 此时变为向右移digits位,即向左移动s.length() - digits位
            int rDigits = -digits;
            int rightDigits = rDigits % s.length();
            return shift(s, s.length() - rightDigits);
        }
    }

    /**
     * 字符串左移,如abcdefghi左移4位后为efghiabcd
     *
     * @param s
     * @return
     */
    public static String reverStr(String s) {
        int low = 0;
        int high = s.length() - 1;
        char[] temp = new char[s.length()];
        while (low <= high) {
            temp[low] = s.charAt(high);
            temp[high] = s.charAt(low);
            low++;
            high--;
        }
        return String.valueOf(temp);
    }

    public static boolean checkTextOverMax(String text, Integer maxLength) {
        if (!isNullOrEmpty(text) && text.length() > maxLength) {
            return true;
        }
        return false;
    }


    public static String preLastConcat(String str, String target) {

        if (!isNullOrEmpty(str) && !isNullOrEmpty(target)) {
            StringBuilder sb = new StringBuilder();
            sb.append(str);
            sb.append(target);
            sb.append(str);
            return sb.toString();
        }


        return null;
    }

    public static String nameReplace(String strPre, String strAft, String content) {
        if (!isNullOrEmpty(strPre) && !isNullOrEmpty(content)) {
            return content.replaceAll(strPre, strAft);
        }
        return null;
    }

    public static String generate32UUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static Long getLastHotelLocationIdFromSeries(String idSeries) {
        String idStr = idSeries.substring(idSeries.lastIndexOf("_", idSeries.length() - 2) + 1, idSeries.length() - 1);
        return Long.parseLong(idStr);
    }


    /**
     * 字符串按长度换行
     */
    public static String getStringByEnter(int length, String string) throws Exception {
        for (int i = 1; i <= string.length(); i++) {
            if (string.substring(0, i).getBytes("GBK").length > length) {
                return string.substring(0, i - 1) + System.lineSeparator() +
                        getStringByEnter(length, string.substring(i - 1));
            }
        }
        return string;
    }

    /**
     * @描述 TODO : 将指定的字符串进行倒转
     * @参数 [s]  要倒转的字符串
     * @返回值 java.lang.String 倒转后的字符串
     * @创建人 邓红斌
     * @创建时间 2020-07-14 17:11
     * @修改人和其它信息
     */
    public static String spiltRtoL(String s) {

        StringBuffer sb = new StringBuffer();
        int length = s.length();
        char[] c = new char[length];
        for (int i = 0; i < length; i++) {
            c[i] = s.charAt(i);
        }
        for (int i = length - 1; i >= 0; i--) {
            sb.append(c[i]);
        }

        return sb.toString();
    }

    /**
     * 数字右补齐0
     *
     * @param n 字符总长度
     * @param s 字符传
     * @return
     */
    public static String intLeftFill(int n, Integer s) {
        if (s >= Math.pow(10, n))
            return s.toString();
        return String.format("%0" + n + "d", s);
    }

    /**
     * 判断字符串是否包含指定特殊符号，包含返回true 否则返回flase
     */
    public static boolean decide(String str) {
        //严格
//        String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        //宽松
        String regEx = "[`$^{}~]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        boolean b = m.find();
        return b;
    }


    public static boolean isValidDate(String str) {
        boolean convertSuccess = true;
        // 指定日期格式为四位年/两位月份/两位日期，注意yyyy-MM-dd区分大小写；
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            // e.printStackTrace();
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            convertSuccess = false;
        }
        return convertSuccess;
    }


    public static boolean isDate(String date)
    {
        /**
         * 判断日期格式和范围
         */
        String rexp = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
        Pattern pat = Pattern.compile(rexp);
        Matcher mat = pat.matcher(date);
        boolean dateType = mat.matches();
        return dateType;
    }

    /**
     * 判断字符串是否是数字类型
     */
    public static boolean isInteger(String str){
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    public static String[] splitTrim(@Nullable String str, @Nullable String delimiter) {
        return delimitedListToStringArray(str, delimiter, " \t\n\n\f");
    }

    public static boolean isNotBlank(final CharSequence cs) {
        return hasText(cs);
    }

    public static StringBuilder appendBuilder(StringBuilder sb, CharSequence... strs) {
        CharSequence[] var2 = strs;
        int var3 = strs.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            CharSequence str = var2[var4];
            sb.append(str);
        }

        return sb;
    }

    public static String removeSuffix(CharSequence str, CharSequence suffix) {
        if (!isEmpty(str) && !isEmpty(suffix)) {
            String str2 = str.toString();
            return str2.endsWith(suffix.toString()) ? subPre(str2, str2.length() - suffix.length()) : str2;
        } else {
            return "";
        }
    }

    public static boolean isEmpty(@Nullable Object str) {
        return str == null || "".equals(str);
    }

    public static String subPre(CharSequence string, int toIndex) {
        return sub(string, 0, toIndex);
    }

    public static String sub(CharSequence str, int fromIndex, int toIndex) {
        if (isEmpty(str)) {
            return "";
        } else {
            int len = str.length();
            if (fromIndex < 0) {
                fromIndex += len;
                if (fromIndex < 0) {
                    fromIndex = 0;
                }
            } else if (fromIndex > len) {
                fromIndex = len;
            }

            if (toIndex < 0) {
                toIndex += len;
                if (toIndex < 0) {
                    toIndex = len;
                }
            } else if (toIndex > len) {
                toIndex = len;
            }

            if (toIndex < fromIndex) {
                int tmp = fromIndex;
                fromIndex = toIndex;
                toIndex = tmp;
            }

            return fromIndex == toIndex ? "" : str.toString().substring(fromIndex, toIndex);
        }
    }
}